package editor;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;


public class EditorTrame extends JPanel implements TableModelListener, Serializable
{
    private transient Vector changeSelectListeners;
    private transient Vector SendTrameListeners;
    private LinkedList dataTrame = new LinkedList();
    //java.util.List dataTrame = Collections.synchronizedList(new LinkedList());
    private final String[] names = {"ind", "valeur"};
    private TrameTableModel dataModel = new TrameTableModel();
    private JTable jTable = new JTable(dataModel);
    private JScrollPane jScrollPane = new JScrollPane(jTable);
    private BorderLayout borderLayout1 = new BorderLayout();

    public EditorTrame()
    {
	try
	{
	    jbInit();
	}
	catch(Exception e)
	{
	    e.printStackTrace();
	}
	byte[] trameInit ={(byte)0x00, (byte)0x00};
	setTrame(trameInit);
    }

    private void jbInit() throws Exception
    {
	this.setBackground(Color.white);
	this.setEnabled(true);
	this.setMaximumSize(new Dimension(130, 120));
	this.setMinimumSize(new Dimension(130, 100));
	this.setPreferredSize(new Dimension(130, 120));
	this.setLayout(borderLayout1);

	jTable.setVerifyInputWhenFocusTarget(false);
	jTable.setAutoCreateColumnsFromModel(false);
	jTable.setCellSelectionEnabled(true);
	jTable.setSelectionMode(0);
	jTable.setSelectionBackground(new Color(220, 220, 220));
	jTable.addKeyListener(new java.awt.event.KeyAdapter() {
	    public void keyPressed(KeyEvent e) {
		jTable_keyPressed(e);
	    }
	});

	RegistreTableCellEditor cellEditor = new RegistreTableCellEditor();
	TableColumnModel columnModel = jTable.getColumnModel();
	TableColumn tc0 = columnModel.getColumn(0);
	TableColumn tc1 = columnModel.getColumn(1);
	tc1.setCellRenderer( new RegistreTableCellRenderer());
	tc1.setCellEditor(cellEditor);
	jTable.setFont(cellEditor.getFont());
	int w1 = cellEditor.getDimensions().width;
	int h1 = cellEditor.getDimensions().height;
	jTable.setRowHeight(h1);

	tc1.setMaxWidth(w1);
	tc1.setMinWidth(w1);
	java.awt.FontMetrics l = jTable.getFontMetrics(jTable.getFont());
	tc0.setCellRenderer( new IndiceTableCellRenderer());
	tc0.setMaxWidth(l.charWidth('0') * 3);
	tc0.setMinWidth(l.charWidth('0') * 3);

	jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
	//jScrollPane.setViewportBorder(BorderFactory.createEtchedBorder());
	jScrollPane.getViewport().setBackground(Color.white);
	jScrollPane.setBorder(null);
	jScrollPane.setPreferredSize(new Dimension(130, 120));
	jScrollPane.setRequestFocusEnabled(false);
	jScrollPane.setVerifyInputWhenFocusTarget(false);

	ToolTipManager.sharedInstance().unregisterComponent(jTable);
	ToolTipManager.sharedInstance().unregisterComponent(jTable.getTableHeader());

	this.add(jScrollPane, BorderLayout.CENTER);

	// pour debug: => tableChanged
	// TableModel tableModel = jTable.getModel();
	// dataModel.addTableModelListener(this);
    }
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    public void tableChanged(TableModelEvent e)
    {
	System.out.println("tableChanged !!");
	if (e.getType() != TableModelEvent.UPDATE)
	 return;
	int ligne = e.getFirstRow();
	int colonne = e.getColumn();
	int value = ((Integer)jTable.getModel().getValueAt(ligne, colonne)).intValue();
	System.out.println("UPDATE: " + value);
    }

    void jTable_keyPressed(KeyEvent e)
    {
	int r;
	switch (e.getKeyCode())
	{
	    case KeyEvent.VK_LEFT:
		e.consume();
		break;
	    case KeyEvent.VK_RIGHT:
		e.consume();
		break;

	    case KeyEvent.VK_UP:
		break;
	    case KeyEvent.VK_DOWN:
		break;

	    case KeyEvent.VK_END:
		//r = jTable.getRowCount();
		//editCell(r);
		//e.consume();
		break;
	    case KeyEvent.VK_HOME:
		//r = jTable.getRowCount();
		//editCell(0);
		//e.consume();
		break;

	    case KeyEvent.VK_PAGE_DOWN:

		break;
	    case KeyEvent.VK_PAGE_UP:

		break;

	    case KeyEvent.VK_ENTER:
		r = jTable.getSelectedRow();
		editCell(r);
		e.consume();
		break;
	}
    }

    void editCell(int r)
    {
	RegistreTableCellEditor c = (RegistreTableCellEditor)jTable.getCellEditor(r,1);
	jTable.editCellAt(r, 1, new EventObject(this));
	c.requestFocus();
    }

//******************************************************************************
//******************************************************************************

    class IndiceTableCellRenderer extends JLabel implements TableCellRenderer
    {
	public IndiceTableCellRenderer()
	{
	    super();
	    this.setHorizontalAlignment(JLabel.CENTER);
	    this.setBorder(BorderFactory.createEtchedBorder());
	    this.setBackground(Color.gray);
	    this.setForeground(Color.white);
	    this.setOpaque(true);
	}

	public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean asFocus, int row, int column)
	{
	    this.setText(Integer.toString(((Integer)value).intValue()));
	    if (asFocus)
	    {
	       changeSelect(row);
	    }
	    return this;
	}
    }

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    class RegistreTableCellRenderer extends RegisterEditor implements TableCellRenderer
    {
	public RegistreTableCellRenderer()
	{
	    super();
	    setEdit(false);
	    setCHex(false);
	    setNbreCar(8);
	    setUnselColor(new Color(200, 200, 200));
	    setFocusColor(new Color(230, 230, 230));
	}

	public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean asFocus, int row, int column)
	{
	   // System.out.println("RegistreTableCellRenderer.getTableCellRendererComponent isSelected:" + isSelected + " asFocus:" + asFocus + " row:" + row);
	    setVal(((Integer)value).intValue());
	    setSelect(isSelected);
	    if(isSelected)changeSelect(row);
	    return this;
	}
    }

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    public class RegistreTableCellEditor extends RegisterEditor implements TableCellEditor
    {
	private EventListenerList listenerList = new EventListenerList();
	private ChangeEvent event = new ChangeEvent(this);

	public RegistreTableCellEditor()
	{
	    super();
	    setEdit(true);
	    setCHex(false);
	    setNbreCar(8);
	    setUnselColor(new Color(212, 208, 200));
	    //setFocusColor(Color.white);
	}

	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
	{
	    //System.out.println("RegistreTableCellEditor.getTableCellEditorComponent isSelected: " + isSelected + " row: " + row);
	    setVal(((Integer)value).intValue());
	    //setSelect(true);
	    changeSelect(row);

	    return this;
	}

	public boolean isCellEditable(EventObject anEvent)
	{
	    return true;
	}

	public boolean shouldSelectCell(EventObject anEvent)
	{
	    return true;
	}

	public void cancelCellEditing()
	{
	    fireEditingCanceled();
	}

	public boolean stopCellEditing()
	{
	    fireEditingStopped();
	    return true;
	}

	public Object getCellEditorValue()
	{
	    return new Integer(getVal());
	}

	public void addCellEditorListener(CellEditorListener l)
	{
	    listenerList.add(CellEditorListener.class, l);
	}

	public void removeCellEditorListener(CellEditorListener l)
	{
	    listenerList.remove(CellEditorListener.class, l);
	}

	protected void fireEditingStopped()
	{
	    Object[] listeners = listenerList.getListenerList();
	    for (int i= listeners.length -2; i >= 0; i-=2)
	    {
		((CellEditorListener)listeners[i+1]).editingStopped(event);
	    }
	}

	protected void fireEditingCanceled()
	{
	    Object[] listeners = listenerList.getListenerList();
	    for (int i= listeners.length -2; i >= 0; i-=2)
	    {
		((CellEditorListener)listeners[i+1]).editingCanceled(event);
	    }
	}
    }

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    class TrameTableModel extends AbstractTableModel
    {
	public TrameTableModel(){}
	public int getColumnCount() { return names.length; }
	public int getRowCount() { return dataTrame.size();}
	public Object getValueAt(int row, int col)
	{
	    if (col == 0) return new Integer(row);
	    else return dataTrame.get(row);
	}
	public String getColumnName(int column) {return names[column];}
	public Class getColumnClass(int col)
	{
	    return getValueAt(0,col).getClass();
	}
	public boolean isCellEditable(int row, int col) {return (col==1);}
	public void setValueAt(Object aValue, int row, int column)
	{
	    //System.out.println("setValueAt: " + row + ":" + column);
	    if (row < dataTrame.size())
		if (column == 1) dataTrame.set(row, aValue);
	}
    }

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//          gestion envoi trame
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    volatile byte[] barrTemp;

    public byte[] getTrame()
    {
	jTable.editingStopped(new ChangeEvent(this));
	int l = dataTrame.size();
	barrTemp = new byte[l];
	for (int i= 0; i< l; i++)
	{
	    barrTemp[i] = (byte)((Integer)(dataTrame.get(i))).byteValue();
	}
	return barrTemp;
    }

    public void setTrame(byte[] barr)
    {
	jTable.editingStopped(new ChangeEvent(this));
	dataTrame.clear();
	int l = barr.length;
	for (int i= 0; i < l; i++)
	{
	    dataTrame.add(new Integer(barr[i]));
	}
	dataModel.fireTableDataChanged();
    }

    public void sendTrame()
    {
	ActionEvent actionEvt = new ActionEvent(this, 0, "trameI2c");
	fireSendTramePerformed(actionEvt);
	Thread.currentThread().yield(); // important !
	setTrame(barrTemp);
    }

    public synchronized void removeSendTrameListener(SendTrameListener l)
    {
	if (SendTrameListeners != null && SendTrameListeners.contains(l))
	{
	    Vector v = (Vector) SendTrameListeners.clone();
	    v.removeElement(l);
	    SendTrameListeners = v;
	}
    }

    public synchronized void addSendTrameListener(SendTrameListener l)
    {
	Vector v = SendTrameListeners == null ? new Vector(1) : (Vector) SendTrameListeners.clone();
	if (!v.contains(l))
	{
	    v.addElement(l);
	    SendTrameListeners = v;
	}
    }

     public void fireSendTramePerformed(ActionEvent e)
    {
	if (SendTrameListeners != null) {
	    Vector listeners = SendTrameListeners;
	    int count = listeners.size();
	    for (int i = 0; i < count; i++)
	    {
		((SendTrameListener) listeners.elementAt(i)).sendTramePerformed(e);
	    }
	}
    }

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//          gestion des octets de la trame
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


    public void addByte()
    {
	jTable.editingStopped(new ChangeEvent(this));
	int rowCount = jTable.getRowCount();
	int rowSelected = jTable.getSelectedRow();

	if ((rowSelected >= 0))
	{
	    dataTrame.add(rowSelected+1, new Integer(0));
	    dataModel.fireTableRowsInserted(rowSelected+1, 0);
	    changeSelect(jTable.getSelectedRow());
	}
    }

    public void removeByte()
    {
	jTable.editingStopped(new ChangeEvent(this));
	int rowCount = dataModel.getRowCount();
	int rowSelected = jTable.getSelectedRow();
	if ((rowCount > 1) & (rowSelected >= 0))
	{
	    dataTrame.remove(rowSelected);
	    dataModel.fireTableRowsDeleted(rowSelected, rowSelected);
	    changeSelect(jTable.getSelectedRow());
	}
    }


    private void changeSelect(int row)
    {
	ActionEvent actionEvt = new ActionEvent(this, row, "edit");
	fireChangeSelectPerformed(actionEvt);
    }

    public synchronized void removeChangeSelectListener(ChangeSelectListener l)
    {
	if (changeSelectListeners != null && changeSelectListeners.contains(l))
	{
	    Vector v = (Vector) changeSelectListeners.clone();
	    v.removeElement(l);
	    changeSelectListeners = v;
	}
    }

    public synchronized void addChangeSelectListener(ChangeSelectListener l)
    {
	Vector v = changeSelectListeners == null ? new Vector(1) : (Vector) changeSelectListeners.clone();
	if (!v.contains(l))
	{
	    v.addElement(l);
	    changeSelectListeners = v;
	}
    }

    public void fireChangeSelectPerformed(ActionEvent e)
    {
	if (changeSelectListeners != null) {
	    Vector listeners = changeSelectListeners;
	    int count = listeners.size();
	    for (int i = 0; i < count; i++)
	    {
		((ChangeSelectListener) listeners.elementAt(i)).changeSelectPerformed(e);
	    }
	}
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
	oos.defaultWriteObject();
    }
    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
	ois.defaultReadObject();
    }

}